package com.user_chat.chat.websocket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.user_chat.chat.controller.UserController;
import com.user_chat.chat.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/chat/{username}")
@Component
public class WebSocketApplication {

    //日志
    private static final Logger log = LoggerFactory.getLogger(WebSocketApplication.class);


    //sessionMap,记录session连接
    public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    //这里可能耦合度有些大，后面服务拆分记得修改
    private static UserController userController;

    @Autowired
    public void setUserController(UserController userController) {
        WebSocketApplication.userController = userController;
    }

    private static UserService userService;

    @Autowired
    public void setUserService(UserService userService){
        WebSocketApplication.userService=userService;
    }

    /**
     * 连接websocket调用的方法
     * @param session
     * @param username
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username){
        log.info("执行了！"+username);
        //1.存放username-session映射关系
        sessionMap.put(username,session);

        //向控制台输出信息
        log.info("新用户加入:{},当前在线人数{}",username,sessionMap.size());

        //2.创建在线用户群
        JSONObject onlineUsers = new JSONObject();
        //3.创建在线用户列表
        JSONArray onlineUserList = new JSONArray();
        //4.创建映射对onlineUsers:onlineUserList
        onlineUsers.put("onlineUsers",onlineUserList);

        //5.循环创建每个用户，效果如：
        // [{username:liangwenjun,url:xxxx},{username:xiaobai,url:xxxx}]
        for (String uname : sessionMap.keySet()) {
            //创建json对象
            JSONObject jsonObject = new JSONObject();
            //存放名字
            jsonObject.put("username",uname);
            String url = null;
            //存放url
            jsonObject.put("url",url);
            //每个jsonObject为{username:liangwenjun,url:用户头像}
            //添加到在线用户列表
            onlineUserList.add(jsonObject);
        }

        //6.转换json字符串
        String message=JSON.toJSONString(onlineUsers);

        //7.发送给所有用户，向更新当前在线状况，给前端更新在线用户
        this.sendAllMessageToAllUsersInit(message);
    }

    /**
     * 发送消息方法
     * @param message
     */
    @OnMessage
    public void onMessage(String message){

        //处理一下时间
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        String nowTime = now.format(dateTimeFormatter);

        //获取json数据
        JSONObject jsonData = JSON.parseObject(message);

        //添加时间之后，再重新变换成json字符串给message
        jsonData.put("publishTime",nowTime);
        message = jsonData.toJSONString();

        log.info("message:{}",jsonData);

        //判断是群发还是私发
        Boolean isClusterSend = jsonData.getBoolean("isClusterSend");

        //如果是群发,则执行群发方法
        if(isClusterSend){
            this.sendAllMessageToAllUsers(message);
            return;
        }

        //否则就是就是私发

        //2.获取json数据的target目标用户
        String target = jsonData.getString("target");

        //3.获取目标用户对应的session连接
        Session targetSession = sessionMap.get(target);

        //4.把这个消息传递到对应的session连接
        this.sendMessageToOneUser(message,targetSession);
    }



    @OnClose
    public void onClose(Session session,@PathParam("username") String username){
        log.info(username+"断开了");

        //移除用户名-session
        sessionMap.remove(username);


        //发送消息，用于前端更新在线人数信息
        JSONObject onlineUsers = new JSONObject();

        JSONArray onlineUserList = new JSONArray();

        onlineUsers.put("onlineUsers",onlineUserList);

        for (String uname : sessionMap.keySet()) {
            //创建json对象
            JSONObject jsonObject = new JSONObject();
            //存放名字
            jsonObject.put("username",uname);

            String url = null;
            //存放url
            jsonObject.put("url",url);
            //每个jsonObject为{username:liangwenjun,url:用户头像}
            onlineUserList.add(jsonObject);
        }

        String message=JSON.toJSONString(onlineUsers);

        this.sendAllMessageToAllUsersInit(message);


    }


    /**
     * 群体发送消息，群聊用
     * @param message
     */
    private void sendAllMessageToAllUsers(String message) {
        //1.获取到所有的用户
        Set<String> users = sessionMap.keySet();

        //2.循环发送消息,并把json对象的目标对象进行修改
        //转挂成json对象
        try {
            JSONObject jsonObj = JSONObject.parseObject(message);
            for (String targetUser : users) {
                //循环取出session
                Session session = sessionMap.get(targetUser);
                //循环设置目标对象
                jsonObj.put("target",targetUser);
                //打印
                log.info(jsonObj.toString());
                //循环发送消息
                session.getBasicRemote().sendText(jsonObj.toJSONString());
            }
        } catch (IOException e) {
            log.info("群发出问题了！");
        }

    }



    /**
     * 集体发送消息,初始连接
     */
    private void sendAllMessageToAllUsersInit(String message){
        //1.获取到所有session
        Collection<Session> sessions = sessionMap.values();

        //2.根据每个session连接逐个发送消息
        for (Session session : sessions) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                log.error("服务器群发消息失败！！！");
            }
        }
    }

    /**
     * 发送一个消息给指定用户
     */
    private void sendMessageToOneUser(String message,Session targetSession){
        //1.先解析message的json字符串
        JSONObject data = JSON.parseObject(message);

        //2.获取源用户、源头像url、目标用户、目标头像url、内容
        String source = data.getString("source");
        String target = data.getString("target");


        message=data.toJSONString();
        String content = data.getString("content");

        log.info("{}给{}发送了{}",source,target,content);

        //2.根据目标session发送信息
        try {
            targetSession.getBasicRemote().sendText(message);
        } catch (IOException e) {
            log.error("发送消息给用户{}有问题",target);
        }


    }
}
